import {
  Component,
  OnInit,
  AfterViewInit,
  OnDestroy,
  Input,
  Output,
  EventEmitter,
  ElementRef,
  ViewChild,
} from '@angular/core';
import * as Blockly from 'blockly';
import { javascriptGenerator } from 'blockly/javascript';
import { initBlockly } from './core/blockly-init';
import { load, save } from './core/serialization';
import { registerBlocks } from './blocks';
import { registerGenerators } from './generators';
import {
  CustomFunctionService,
  CustomFunction,
} from '../services/custom-function.service';
import { registerCustomFunctionBlocks } from './blocks/custom-function-blocks';
import { registerCustomFunctionGenerators } from './generators/custom-function-generators';
import { createCustomFunctionCategory } from './toolbox/custom-function-category';
import { categories } from './toolbox/categories';

@Component({
  selector: 'app-blockly',
  templateUrl: './blockly.component.html',
  styleUrls: ['./blockly.component.scss'],
})
export class BlocklyComponent implements OnInit, AfterViewInit, OnDestroy {
  @ViewChild('blocklyDiv') blocklyDiv!: ElementRef;

  @Input() importVariableCallback?: () =>
    | string
    | null
    | Promise<string | null>;

  @Output() codeChange = new EventEmitter<string>();
  @Output() workspaceChange = new EventEmitter<any>();

  workspace: Blockly.WorkspaceSvg | undefined;
  customFunctions: CustomFunction[] = [];
  toolbox: any;

  constructor(private customFunctionService: CustomFunctionService) {}

  ngOnInit(): void {
    // 注册基本块和生成器
    // registerBlocks();
    // registerGenerators();

    // // 初始化工具箱
    // this.toolbox = {
    //   kind: 'categoryToolbox',
    //   contents: Object.values(categories)
    // };

 
  }

  ngAfterViewInit(): void {
    // Initialize Blockly after the view is initialized
    this.initBlockly();
  }

  ngOnDestroy() {
    // 清理资源
    if (this.workspace) {
      this.workspace.dispose();
    }

    // 移除窗口大小变化监听器
    window.removeEventListener('resize', this.onResize);
  }

  private initBlockly(): void {
    this.workspace = initBlockly(
      this.blocklyDiv.nativeElement,
      this.importVariableCallback
    );
       // 获取自定义函数
    this.loadCustomFunctions();
    load(this.workspace);



    // 监听工作区变化事件
    this.workspace.addChangeListener(this.onWorkspaceChange.bind(this));

    // 添加窗口大小变化监听器
    window.addEventListener('resize', this.onResize.bind(this));

    // 初始调整大小
    this.onResize();
  }

  private onWorkspaceChange(event: any) {
    if (
      event.type === Blockly.Events.BLOCK_CHANGE ||
      event.type === Blockly.Events.BLOCK_CREATE ||
      event.type === Blockly.Events.BLOCK_DELETE ||
      event.type === Blockly.Events.BLOCK_MOVE
    ) {
      // 生成代码
      const code = javascriptGenerator.workspaceToCode(this.workspace);
      this.codeChange.emit(code);

      // 发出工作区变化事件
      this.workspaceChange.emit(event);
    }
  }

  private onResize() {
    // Make sure the workspace exists
    if (this.workspace) {
      // Force a resize of the workspace
      Blockly.svgResize(this.workspace);

      // Get the parent element dimensions
      const parentWidth =
        this.blocklyDiv.nativeElement.parentElement.offsetWidth;
      const parentHeight =
        this.blocklyDiv.nativeElement.parentElement.offsetHeight;

      // Set the blockly div dimensions to match parent
      this.blocklyDiv.nativeElement.style.width = parentWidth + 'px';
      this.blocklyDiv.nativeElement.style.height = parentHeight + 'px';

      // Resize the workspace
      Blockly.svgResize(this.workspace);
    }
  }

  // Method to generate code from the workspace
  public generateCode(): string {
    if (this.workspace) {
      const code = javascriptGenerator.workspaceToCode(this.workspace);
      console.log(code);
      return code;
    }
    return '';
  }

  // Method to run the generated code
  public runCode(): void {
    try {
      const code = this.generateCode();
      // Use Function constructor to create a function from the code
      // Note: This is for demo purposes only and has security implications in production
      const runFunc = new Function(code);
      runFunc();
    } catch (e) {
      console.error('Error executing code:', e);
      alert('Error executing code: ' + e);
    }
  }

  // 公共方法，用于保存工作区为XML
  public saveWorkspace(): void {
    if (this.workspace) {
      save(this.workspace);
    } else {
      console.warn('Cannot save workspace: workspace is undefined');
    }
  }

  // 公共方法，用于从XML加载工作区
  public importWorkspace(xmlText: string): void {
    try {
      this.workspace?.clear();
      // const xmlDom = Blockly.Xml.textToDom(xmlText);
      const parser = new DOMParser();
      const dom = parser.parseFromString(xmlText, 'text/xml');
      Blockly.Xml.domToWorkspace(dom.documentElement, this.workspace!);
    } catch (e) {
      console.error('加载工作区时出错:', e);
      throw e;
    }
  }
  public exportWorkspace(): string {
    const xmlDom = Blockly.Xml.workspaceToDom(this.workspace!);
    return Blockly.Xml.domToText(xmlDom);
  }
  public importVariable(variable: any) {
    // Otherwise create a new variable block
    const xml = `<xml><block type="text"><field name="TEXT" id="${variable.id}">${variable.name}</field></block></xml>`;
    const parser = new DOMParser();
    const dom = parser.parseFromString(xml, 'text/xml');
    const block = Blockly.Xml.domToBlock(
      dom.firstChild?.firstChild as Element,
      this.workspace!
    );

    // Refresh the toolbox to show the new variable
    this.workspace?.refreshToolboxSelection();

    if (block) {
      // Position the new block near the center of the workspace
      const metrics = this.workspace?.getMetrics();
      if (metrics) {
        block.moveBy(metrics.viewWidth / 2, metrics.viewHeight / 2);
      }
    }
  }

  private loadCustomFunctions() {
    // 阻止重复加载自定义函数
    if (this.customFunctions.length > 0) {
      console.log('Custom functions already loaded, skipping loading');
      return;
    }
    
    this.customFunctionService.getCustomFunctions().subscribe(
      (functions) => {
        this.customFunctions = functions;
        console.log("this.customFunctions", this.customFunctions);
        // 注册自定义函数块和生成器
        registerCustomFunctionBlocks(this.customFunctions);
        registerCustomFunctionGenerators(this.customFunctions);

        // 更新工具箱
        this.updateToolbox();
      },
      (error) => {
        console.error('获取自定义函数失败:', error);
      }
    );
  }

  private updateToolbox() {
    if (!this.workspace) return;

    // 创建自定义函数类别
    const customFunctionCategory = createCustomFunctionCategory(
      this.customFunctions
    );

    // 更新工具箱
    const newToolbox = {
      kind: 'categoryToolbox',
      contents: [...Object.values(categories), customFunctionCategory],
    };
    console.log("newToolbox",newToolbox);
    // 应用新工具箱
    this.workspace.updateToolbox(newToolbox);
  }
}
